package models;

import java.io.Serializable;
import java.math.BigDecimal;

import javax.persistence.*;

import java.util.Date;
import java.util.EnumSet;
import java.util.Set;

/**
 * The persistent class for the transaction database table.
 * 
 */
@Entity
@Table(name = "TRANSACTION")
public class Transaction implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @TableGenerator(
            name = "TRANSACTION_SEQ",
            table = "SEQUENCE",
            pkColumnName = "NAME",
            pkColumnValue = "TRANSACTION_SEQ",
            valueColumnName = "CNT",
            initialValue = 10000,
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "TRANSACTION_SEQ")
    @Column(unique = true, nullable = false)
    private Integer id;

    private double amount;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "COMPLETION_D")
    private Date completionD;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATE_D")
    private Date createD;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "EXEC_D")
    private Date execD;

    @Column(name = "EXT_ID", length = 100)
    private String extId;

    @Column(name = "EXT_STATUS")
    private int extStatus;

    @Column(name = "FROM_ACCOUNT")
    private Integer fromAccount;

    @Column(name = "FROM_ACTOR_BALANCE")
    private double fromActorBalance;

    @Column(name = "FROM_AID")
    private Integer fromAid;

    @Column(name = "INIT_AID")
    private Integer initAid;

    @Column(name = "LOAN_ID")
    private Integer loanId;

    @Column(name = "ORDER_DETAIL_ID")
    private Integer orderDetailId;

    @Column(name = "ORDER_ID")
    private Integer orderId;

    @Column(name = "PAY_DETAIL_ID")
    private Integer payDetailId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "SCHEDULE_D")
    private Date scheduleD;

    private int status;

    @Column(name = "TO_ACCOUNT")
    private Integer toAccount;

    @Column(name = "TO_ACTOR_BALANCE")
    private double toActorBalance;

    @Column(name = "TO_AID")
    private Integer toAid;

    private int type;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATE_D")
    private Date updateD;

    public Transaction(
            Type type,
            Integer initActor,
            Integer fromActor,
            Integer toActor,
            Integer acctFrom,
            Integer acctTo,
            double amount,
            Date scheduleDate,
            Integer orderId,
            Integer loanId) {

        this.setType(type);
        this.setAmount(amount);
        this.setInitAid(initActor);
        this.setFromAid(fromActor);
        this.setToAid(toActor);
        this.setFromAccount(acctFrom);
        this.setToAccount(acctTo);
        this.setScheduleD(scheduleDate);
        this.setLoanId(loanId);
        this.setOrderId(orderId);
    }

    public Transaction() {
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public double getAmount() {
        return this.amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public Date getCompletionD() {
        return this.completionD;
    }

    public void setCompletionD(Date completionD) {
        this.completionD = completionD;
    }

    public Date getCreateD() {
        return this.createD;
    }

    public void setCreateD(Date createD) {
        this.createD = createD;
    }

    public Date getExecD() {
        return this.execD;
    }

    public void setExecD(Date execD) {
        this.execD = execD;
    }

    public String getExtId() {
        return this.extId;
    }

    public void setExtId(String extId) {
        this.extId = extId;
    }

    public int getExtStatus() {
        return this.extStatus;
    }

    public void setExtStatus(int extStatus) {
        this.extStatus = extStatus;
    }

    public Integer getFromAccount() {
        return this.fromAccount;
    }

    public void setFromAccount(Integer fromAccount) {
        this.fromAccount = fromAccount;
    }

    public double getFromActorBalance() {
        return this.fromActorBalance;
    }

    public void setFromActorBalance(double fromActorBalance) {
        this.fromActorBalance = fromActorBalance;
    }

    public Integer getFromAid() {
        return this.fromAid;
    }

    public void setFromAid(Integer fromAid) {
        this.fromAid = fromAid;
    }

    public Integer getInitAid() {
        return this.initAid;
    }

    public void setInitAid(Integer initAid) {
        this.initAid = initAid;
    }

    public Integer getLoanId() {
        return this.loanId;
    }

    public void setLoanId(Integer loanId) {
        this.loanId = loanId;
    }

    public Integer getOrderDetailId() {
        return this.orderDetailId;
    }

    public void setOrderDetailId(Integer orderDetailId) {
        this.orderDetailId = orderDetailId;
    }

    public Integer getOrderId() {
        return this.orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public Integer getPayDetailId() {
        return this.payDetailId;
    }

    public void setPayDetailId(Integer payDetailId) {
        this.payDetailId = payDetailId;
    }

    public Date getScheduleD() {
        return this.scheduleD;
    }

    public void setScheduleD(Date scheduleD) {
        this.scheduleD = scheduleD;
    }

    public Status getStatus() {
        Status[] vals = Status.values();
        if (this.status > vals.length - 1 || this.status < 0)
            return null;
        return Status.values()[this.status];
    }

    public void setStatus(Status status) {
        this.status = status.ordinal();
    }

    public Integer getToAccount() {
        return this.toAccount;
    }

    public void setToAccount(Integer toAccount) {
        this.toAccount = toAccount;
    }

    public double getToActorBalance() {
        return this.toActorBalance;
    }

    public void setToActorBalance(double toActorBalance) {
        this.toActorBalance = toActorBalance;
    }

    public Integer getToAid() {
        return this.toAid;
    }

    public void setToAid(Integer toAid) {
        this.toAid = toAid;
    }

    public Type getType() {
        Type[] vals = Type.values();
        if (this.type > vals.length - 1 || this.type < 0)
            return null;
        return Type.values()[this.type];
    }

    public void setType(Type type) {
        this.type = type.ordinal();
    }

    public Date getUpdateD() {
        return this.updateD;
    }

    public void setUpdateD(Date updateD) {
        this.updateD = updateD;
    }

    public enum Status {
        PENDING("Pending"), //0
        EXECUTED("Executed"),//1
        IN_REVIEW("In Review"),//2
        FAILED("Failed"),//3
        DISCARD("Discard"),//4
        CANCELED("Canceled");//5

        private String _name;

        private Status(String name) {
            _name = name;
        }

        public String getName() {
            return _name;
        }

        public boolean isInstatus(Transaction.Status... Statuses) {
            if (Statuses == null)
                return false;
            for (Status s : Statuses) {
                if (s == this)
                    return true;
            }
            return false;
        }
    }

    public enum Type {
        T0_ADD_FUNDS("Add funds to system", true),
        T1_WITHDRAWL("Withdraw funds from system", true),
        T2_LENDER_ISSUE_FUNDS_TO_BORROWER("Transfer money from lender to borrower after loan issued", true),
        T3_PUSH_FUNDS_TO_BORROWER_BANK("Send money to borrower's bank account", true),
        T4_BORROWER_PAY_ORIG_FEE("Borrower pay origination fee", true),
        T5_BORROWER_PAY_MANAGEMENT_FEE("", true),
        T6_LENDER_PAY_SERVICE_FEE("", true),
        T7_BORROWER_PAY_LATE_FEE("", true),
        T8_BORROWER_MTHLY_PAY_TO_LENDER("", true);
        
        
        private String _desc;

        private boolean _active;

        private Type(String desc, boolean active) {
            _desc = desc;
            _active = active;
        }

        public String get_desc() {
            return _desc;
        }

        public boolean is_active() {
            return _active;
        }

    }

    public enum SummaryType {
        DEPOSITS,
        WITHDRAWALS;

        private Set<Type> detail = null;
        static {
            SummaryType.DEPOSITS.detail = EnumSet.of(Type.T0_ADD_FUNDS);

            SummaryType.WITHDRAWALS.detail = EnumSet.of(Type.T1_WITHDRAWL);
        }

        public boolean contains(Type type) {
            return detail.contains(type);
        }

        public Set<Type> getMemberTypes() {
            return this.detail;
        }
    }

}
